/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.myapp.wicket.examples;

import com.myapp.wicket.BaseExamplesPage;
import com.myapp.wicket.behaviors.InputElementFocusBehavior;
import com.myapp.wicket.behaviors.PreventFormSubmitOnEnterBehavior;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.IAjaxCallDecorator;
import org.apache.wicket.ajax.calldecorator.AjaxCallDecorator;
import org.apache.wicket.ajax.calldecorator.AjaxPreprocessingCallDecorator;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;

/**
 * Demonstrates various techniques for contributing Javascript to a 
 * page and other components as well as how to add a precondition Javascript
 * that executes prior to Wicket's generated Ajax call and which
 * can also prevent Wicket's generated Ajax call from executing.
 * 
 * This page demonstrates the following:
 * 1) A form with a behavior that contributes Javascript to 
 * the page and which is to execute when the page loads. In 
 * particular, this script sets the input focus on the first 
 * input (type=text) element.
 * 
 * 2) A form with a behavior that prevents page submission on 
 * enter key pressed when the focus is in an input element. 
 * This is needed when the form should only submit via Ajax.
 * 
 * 3) A specialized AjaxSubmitLink with a behavior that contributes 
 * Javascript to validate input prior to submitting the form via Ajax
 * and which prevents the form submission if the validation fails.
 * 
 * @author Jeff
 */
public final class PrependingAjaxBehaviorPage extends BaseExamplesPage {

    /*
     * A form that submits its input elements via Ajax and which
     * prevents submit on enter key pressed and which sets the 
     * first input element focus.
     */
    private class AjaxForm<T> extends Form<T> {

        public AjaxForm(String id, IModel<T> model) {
            super(id, model);
            // Behavior to prevent the enter key from sumitting the form
            add(new PreventFormSubmitOnEnterBehavior());
            add(new InputElementFocusBehavior());
        }

        public AjaxForm(String id) {
            this(id, null);
        }
    }

    /*
     * An AjaxSubmitLink that contributes Javascript to be executed
     * prior to Wicket's Ajax call and that can also prevent Wicket's
     * Ajax call from executing. Uses cases include performing client
     * side validation and preventing the Ajax form submit should
     * validation fail.
     */
    private abstract class AjaxSubmitLinkWithPrecondition extends AjaxSubmitLink {

        /*
         * Script which returns false if the ajax call shouldn't be made
         */
        private String preconditionJavascript;

        public AjaxSubmitLinkWithPrecondition(String preconditionJavascript, String id, Form<?> form) {
            super(id, form);
            this.preconditionJavascript = preconditionJavascript;
        }

        public AjaxSubmitLinkWithPrecondition(String preconditionJavascript, String id) {
            super(id);
            this.preconditionJavascript = preconditionJavascript;
        }

        /*
         * Returns an instance of our AjaxPreprocessingCallDecorator
         * whose preDecorateScript method modifies the generated
         * script (generated by the AjaxSubmitLink component)
         * by prepending it with our precondition Javascript
         */
        @Override
        protected IAjaxCallDecorator getAjaxCallDecorator() {
            return new AjaxPreprocessingCallDecorator(super.getAjaxCallDecorator()) {

                @Override
                public CharSequence preDecorateScript(CharSequence script) {
                    return preconditionJavascript + script;
                }
                
            };
        }
    }
    
    private String input = "";
    private String entered = "";
    final private Label enteredLabel;

    public PrependingAjaxBehaviorPage() {
        super();

        /*
         * Model for the page
         */
        setDefaultModel(new CompoundPropertyModel<PrependingAjaxBehaviorPage>(this));

        /*
         * Form with behavior to prevent submit on enter key presses
         */
        final AjaxForm<PrependingAjaxBehaviorPage> form = new AjaxForm<PrependingAjaxBehaviorPage>("form");
        add(form);

        /*
         * A Text Field
         */
        final TextField<String> textField = new TextField("input");
        textField.setOutputMarkupId(true);
        form.add(textField);

        /*
         * An AjaxSubmitLink component with behavior
         */

        /*
         * This is the Javascript that will be prepended
         * to the Javascrip that Wicket normally generates
         * for the AjaxSubmitLink. It tests if what the 
         * user keyed in is not a number and if true
         * it exits by returning false, preventing the 
         * remaing script to execute.
         */
        final String preconditionJavascript = "if(isNaN(getElementById('"
                + textField.getMarkupId()
                + "').value) == true || getElementById('"
                + textField.getMarkupId()
                + "').value == ''){ alert('Please enter a valid number');"
                + "getElementById('" + textField.getMarkupId() + "').focus();"
                + "return false;}";
        final AjaxSubmitLinkWithPrecondition submit = new AjaxSubmitLinkWithPrecondition(preconditionJavascript, "submit") {

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                target.focusComponent(textField);
                target.addComponent(textField);
                enteredLabel.setVisible(true);
                entered = "You entered the number " + input;
                input = "";
                target.addComponent(enteredLabel);
            }
        };
        form.add(submit);

        /*
         * A label to display the number entered
         */
        enteredLabel = new Label("entered");
        enteredLabel.setVisible(false);
        enteredLabel.setOutputMarkupPlaceholderTag(true);
        add(enteredLabel);
    }

    public PrependingAjaxBehaviorPage(PageParameters params) {
        this();
    }
}
